using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Text;
using System.Text.RegularExpressions;
using Lookstone.Configuration;

namespace Lookstone.Utility
{
	/// <summary>
	/// FormState allows the developer to easily track the position, size, and state of a Form.  It is used on construction and 
	/// destruction to retain the user's last use state of the form.
	/// </summary>
	/// <remarks>Known issues: doesn't work well for anything placed on a non-primary monitor.</remarks>
	public class FormState
	{
		public FormState()
		{
		}

		/// <summary>
		/// This version of the constructor is used primarily to 
		/// serialize the form.
		/// </summary>
		/// <param name="form"></param>
		public FormState(System.Windows.Forms.Form form)
		{
			FormWindowState state = form.WindowState;

			m_windowState = form.WindowState;
			if (m_windowState != FormWindowState.Normal)
			{
				form.SuspendLayout();
				// Normalize the window and get its location
				form.WindowState = FormWindowState.Normal;
			}

			m_location = form.Location;
			m_size = form.ClientSize;

			if (state != m_windowState)
			{
				form.WindowState = state;
				form.ResumeLayout();
			}
		}

		/// <summary>
		/// This constructor takes a string, and prepares the 
		/// FormState object to restore a form to its previous
		/// state.
		/// </summary>
		/// <param name="fromString"></param>
		public FormState(string fromString)
		{
			if (fromString.Length == 0)
			{
				m_isDefault = true;
				return;
			}

			Match match = Regex.Match(fromString, @"Loc={\S+}");
			MatchCollection
						matches;

			if (match.Success)
			{
				matches = Regex.Matches(match.ToString(), @"[0-9]+");

				if (matches.Count == 2)
				{
					m_location.X = int.Parse(matches[0].ToString());
					m_location.Y = int.Parse(matches[1].ToString());
				}
			}
			else
			{
				m_isDefault = true;
				return;
			}

			match = Regex.Match(fromString, @"Size={.+}");
			if (match.Success)
			{
				matches = Regex.Matches(match.ToString(), @"[0-9]+");

				if (matches.Count == 2)
				{
					m_size.Width = int.Parse(matches[0].ToString());
					m_size.Height = int.Parse(matches[1].ToString());
				}
			}

			match = Regex.Match(fromString, @"State=[a-zA-Z]+\b");
			m_windowState = (FormWindowState)FormWindowState.Parse(typeof(FormWindowState),
				match.ToString().Remove(0, 6), true);
		}

		public Point Location
		{
			get
			{
				return m_location;
			}
			set
			{
				m_location = value;
			}
		}

		public Size FormSize
		{
			get
			{
				return m_size;
			}
			set
			{
				m_size = value;
			}
		}

		public FormWindowState WindowState
		{
			get
			{
				return m_windowState;
			}
			set
			{
				m_windowState = value;
			}
		}

		/// <summary>
		/// RestoreState will restore the form to the original position, size, 
		/// and state
		/// </summary>
		/// <param name="form">The form to be acted upon</param>
		public void RestoreState(System.Windows.Forms.Form form)
		{
			form.AutoScaleMode = AutoScaleMode.None;

			if (m_isDefault)
				return;

			Size windowSize = m_size;

			if (form.AutoScroll)
			{
				if (form.HorizontalScroll.Visible)
					windowSize.Height -= System.Windows.Forms.SystemInformation.HorizontalScrollBarHeight;
				if (form.VerticalScroll.Visible)
					windowSize.Width -= System.Windows.Forms.SystemInformation.VerticalScrollBarWidth;
			}

			form.SuspendLayout();
			form.Location = m_location;
			form.ClientSize = windowSize;
			form.WindowState = m_windowState;

			form.StartPosition = FormStartPosition.Manual;
			form.ResumeLayout(true);
			form.TopLevelControl.Refresh();
			Application.DoEvents();
		}

		/// <summary>
		/// Restores only the position (not size or state) of a form
		/// </summary>
		/// <param name="form">The form to be acted upon</param>
		public void RestoreLocation(System.Windows.Forms.Form form)
		{
			if (m_isDefault)
				return;

			form.SuspendLayout();
			form.Location = m_location;
			form.StartPosition = FormStartPosition.Manual;
			form.ResumeLayout(true);
			form.TopLevelControl.Refresh();
		}

		/// <summary>
		/// Returns a string containing position, size, and state information
		/// for serialization
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(75);

			stringBuilder.AppendFormat("{{Loc={0}; Size={1}; State={2}}}",
				m_location.ToString(), m_size.ToString(), m_windowState.ToString());
			return stringBuilder.ToString();
		}

		public bool IsDefault
		{
			get { return m_isDefault; }
		}

		protected bool m_isDefault = false;
		protected Point m_location = new Point(0, 0);
		protected Size m_size = new Size(640, 400);
		protected FormWindowState m_windowState = FormWindowState.Normal;

		public static void SaveFormState(Form form, string formName = null)
		{
			FormState state = new FormState(form);

			if (string.IsNullOrEmpty(formName))
				formName = form.GetType().ToString();

			AppSettings.Settings.SetSetting(@"ScreenSettings", formName, state.ToString());
		}

		public static void RestoreFormLocation(Form form, string formName = null)
		{
			if (string.IsNullOrEmpty(formName))
				formName = form.GetType().ToString();

			FormState state = new FormState(AppSettings.Settings.GetSetting("ScreenSettings", formName));

			state.RestoreLocation(form);
		}

		public static void RestoreFormState(Form form, string formName = null)
		{
			if (string.IsNullOrEmpty(formName))
				formName = form.GetType().ToString();

			FormState state = new FormState(AppSettings.Settings.GetSetting("ScreenSettings", formName));

			state.RestoreState(form);
		}
	}
}
